import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, Repository, Between, Like } from 'typeorm';

import WipOrderReport from '@main/entities/service/admin/wip/wip-order-report.entity';
import ProductionOrder from '@main/entities/service/admin/production/production-order.entity';
import SysUser from '@main/entities/service/admin/sys/sys-user.entity';
import { ApiException } from '@main/common/exceptions/api.exception';
import { generateExcelFn } from '@main/excel';
import { format } from 'date-fns';

@Injectable()
export class ReportFormStaffReportStatisticsService {
  constructor(
    @InjectRepository(WipOrderReport)
    private orderReportRepository: Repository<WipOrderReport>,
    @InjectRepository(ProductionOrder)
    private orderRepository: Repository<ProductionOrder>,
    @InjectRepository(SysUser)
    private userRepository: Repository<SysUser>
  ) {}

  /**
   * 罗列所有配置
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const { userIdList, reportDate, fastSearch, ids = [] } = entity;

    const where: any[] = []; // 初始化为数组以便后续拼接

    // 处理 userIdList 进行匹配
    if (reportDate && reportDate.length) {
      if (userIdList && userIdList.length) {
        if (fastSearch) {
          for (const item of userIdList) {
            where.push({
              reportFinishStatus: 1,
              reportUserList: Like(`%${item}%`),
              reportTime: Between(reportDate[0], reportDate[1]),
              materialName: Like(`%${fastSearch}%`),
              materialCode: Like(`%${fastSearch}%`),
            });
          }
        } else {
          for (const item of userIdList) {
            where.push({
              reportFinishStatus: 1,
              reportUserList: Like(`%${item}%`),
              reportTime: Between(reportDate[0], reportDate[1]),
            });
          }
        }
      } else if (fastSearch) {
        where.push(
          {
            reportFinishStatus: 1,
            materialCode: Like(`%${fastSearch}%`),
            reportTime: Between(reportDate[0], reportDate[1]),
          },
          {
            reportFinishStatus: 1,
            materialName: Like(`%${fastSearch}%`),
            reportTime: Between(reportDate[0], reportDate[1]),
          }
        );
      } else {
        where.push({
          reportFinishStatus: 1,
          reportTime: Between(reportDate[0], reportDate[1]),
        });
      }
    }

    if (ids && ids.length) {
      for (const item of where) {
        item['id'] = In(ids);
      }
    }

    const [list, total] = await this.orderReportRepository.findAndCount({
      where,
      order: {
        updateTime: 'DESC',
      },
      take: pageSize,
      skip: (pageNum - 1) * pageSize,
    });

    const newList = await Promise.all(
      list.map(async (item) => {
        const {
          orderCode,
          reportStatus,
          reportTime,
          reportConfirmNum,
          reportNum,
          goodNum,
          reportUserList,
        } = item;

        let yieldRate: any = 0;

        if (reportStatus) {
          yieldRate = (goodNum / reportConfirmNum) * 100;
        } else {
          yieldRate = (goodNum / reportNum) * 100;
        }

        if (reportTime) {
          item['reportTime'] = format(new Date(reportTime), 'yyyy-MM-dd') as any;
        }

        const obj = await this.orderRepository.findOne({
          where: {
            orderCode,
          },
        });

        obj.materialStandards = `${obj.materialLength}*${obj.materialWidth}*${obj.materialHeight}`;

        const rList = reportUserList.split(',');

        const userNameList = [];

        const nickNameList = [];

        await Promise.all(
          rList.map(async (item) => {
            const user = await this.userRepository.findOne({
              where: {
                id: item,
              },
            });

            if (user) {
              userNameList.push(user.userName);
              nickNameList.push(user.nickName);
            }
          })
        );

        return {
          ...(obj || {}),
          ...item,
          yieldRate: (isNaN(yieldRate) ? 0 : yieldRate).toFixed(2),
          userNameList: userNameList?.join(',') || [],
          nickNameList: nickNameList?.join(',') || [],
        };
      })
    );

    return [newList, total];
  }

  async export(dto, lang) {
    const [list] = await this.page(dto);

    if (!list || !(list as any).length) {
      throw new ApiException(10052);
    }

    const dataList = list;

    return await generateExcelFn(
      {
        sheetName: 'staffReportStatistics',
        mainHeaderList: [
          {
            label: 'userNameList',
          },
          {
            label: 'nickNameList',
          },
          {
            label: 'materialCode',
          },
          {
            label: 'materialName',
          },
          {
            label: 'version',
          },
          {
            label: 'materialStandards',
          },
          {
            label: 'reportTime',
          },
          {
            label: 'reportNum',
          },
          {
            label: 'goodNum',
          },
          {
            label: 'badNum',
          },
          {
            label: 'yieldRate',
          },
        ],
        dataList,
      },
      lang
    );
  }
}
